package com.portal.framework.util;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import net.sf.ezmorph.Morpher;
import net.sf.ezmorph.object.DateMorpher;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessor;
import net.sf.json.util.JSONUtils;
import net.sf.json.util.PropertyFilter;

/**
 * json 工具类
 * 
 * <li> 现在Date类型不能用数组或Collection
 * <li> 日期的格式为[yyyy-MM-dd] 可以自己修改 如：JsonUtil.dateFormat = yyyyMMdd
 * 
 * @author 卢烁波
 * @date 2007-3-10
 */
public class JsonUtil {
	public static String dateFormat = "yyyy-MM-dd";

	private static Morpher dateMorpher = new DateMorpher(
			new String[] { dateFormat });

	/**
	 * 将一个json字符串转换成一个Object对象
	 * 
	 * @param jsonString
	 * @return
	 */
	public static Object getObjectFromJsonString(String jsonString) {
		JSONObject o = JSONObject.fromObject(jsonString);
		return JSONObject.toBean(o);
	}

	/**
	 * 将一个对象转换成Json字符串,包括List,数组等信息
	 * 
	 * 
	 * @param jsonString
	 * @return
	 */
	public static String toJsonString(Object obj) {
		return toJsonString(obj, true);
	}

	/**
	 * 将一个对象转换成Json字符串
	 * 
	 * 
	 * @param jsonString
	 * @param includeCollection
	 *            输出时是否包括List,数组等信息 true=包括,false=不包括.
	 * @return
	 */
	public static String toJsonString(Object obj, boolean includeCollection) {
		if (obj == null) {
			return "{}";
		}
		if (obj.getClass().isArray() && CollectionUtils.empty((Object[]) obj)) {
			return "[]";
		}
		if (obj instanceof Collection
				&& CollectionUtils.empty((Collection) obj)) {
			return "[]";
		}
		JsonConfig config = new JsonConfig();
		DateToStringValueProcessor myDateValueProcessor = new DateToStringValueProcessor();
		myDateValueProcessor.setDateFormat(dateFormat);
		config.registerJsonValueProcessor(Date.class, myDateValueProcessor);

		if (!includeCollection) {
			config.setJavaPropertyFilter(new CollectionPropertyFilter());
		}

		if (obj.getClass().isArray()) {
			return toJsonStringByArray(obj, config);
		}

		if (obj instanceof Collection) {
			return toJsonStringByArray(obj, config);
		}

		JSONObject o = JSONObject.fromObject(obj, config);
		return o.toString();
	}

	private static String toJsonStringByArray(Object arr, JsonConfig config) {
		JSONArray o = JSONArray.fromObject(arr, config);
		return o.toString();
	}

	/**
	 * 将一个json字符串转换成一个对象<BR>
	 * 注意:使用List类型会出错,要使用数组 Object[]
	 * 
	 * @param <T>
	 * @param jsonString
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getObjectFromJsonString(String jsonString,
			Class<T> clazz, JsonConfig config) {
		if (config == null) {
			config = new JsonConfig();
		}
		// DateToStringValueProcessor myDateValueProcessor = new
		// DateToStringValueProcessor();
		// myDateValueProcessor.setDateFormat(dateFormat);
		// config.registerJsonValueProcessor(Date.class, myDateValueProcessor);

		JSONUtils.getMorpherRegistry().registerMorpher(dateMorpher);

		JSONObject o = JSONObject.fromObject(jsonString, config);
		if (clazz == null) {
			return (T) JSONObject.toBean(o);
		} else {
			return (T) JSONObject.toBean(o, clazz);
		}

	}

	/**
	 * 将一个json字符串转换成一个对象<BR>
	 * 注意:使用List类型会出错,要使用数组 Object[]
	 * 
	 * @param <T>
	 * @param jsonString
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getObjectFromJsonString(String jsonString,
			Class<T> clazz) {
		return getObjectFromJsonString(jsonString, clazz, null);
	}

	@SuppressWarnings("unchecked")
	public static <T> T[] getArrayFromJsonString(String jsonString,
			Class<T> clazz) {
		JSONUtils.getMorpherRegistry().registerMorpher(dateMorpher);

		JSONArray arr = JSONArray.fromObject(jsonString);
		return (T[]) JSONArray.toArray(arr, clazz);
	}

	@SuppressWarnings("unchecked")
	public static <T> List<T> getListFromJsonString(String jsonString,
			Class<T> clazz) {
		JSONUtils.getMorpherRegistry().registerMorpher(dateMorpher);

		JSONArray arr = JSONArray.fromObject(jsonString);
		return (List<T>) JSONArray.toList(arr, clazz);
	}

	private static class CollectionPropertyFilter implements PropertyFilter {
		public boolean apply(Object source, String name, Object value) {
			Field f = ClassUtil.getField(source.getClass(), name, null);
			if (f == null) {
				return false;
			}
			if (f.getType().isArray()
					|| f.getType().isAssignableFrom(Collection.class)) {
				return true;
			}

			return false;
		}
	}

	private static class DateToStringValueProcessor implements
			JsonValueProcessor {
		public String dateFormat;

		public Object processArrayValue(Object value, JsonConfig jsonConfig) {
			if (value == null) {
				return null;
			}
			Date d = null;
			if (value instanceof java.sql.Date) {
				d = new Date(((java.sql.Date) value).getTime());
			} else if (value instanceof Date) {
				d = (Date) value;
			}
			if (d != null) {
				return DateTimeUtil.formatDate(d, dateFormat);
			}

			return null;
		}

		public Object processObjectValue(String key, Object value,
				JsonConfig jsonConfig) {
			return processArrayValue(value, jsonConfig);
		}

		public String getDateFormat() {
			return dateFormat;
		}

		public void setDateFormat(String dateFormat) {
			this.dateFormat = dateFormat;
		}
	}

	private static class DateToBeanValueProcessor implements JsonValueProcessor {
		public String dateFormat;

		public Object processArrayValue(Object value, JsonConfig jsonConfig) {
			if (value == null) {
				return null;
			}
			Date d = null;
			if (value instanceof java.sql.Date) {
				d = new Date(((java.sql.Date) value).getTime());
			} else if (value instanceof Date) {
				d = (Date) value;
			}
			if (d != null) {
				return DateTimeUtil.formatDate(d, dateFormat);
			}

			return null;
		}

		public Object processObjectValue(String key, Object value,
				JsonConfig jsonConfig) {
			return processArrayValue(value, jsonConfig);
		}

		public String getDateFormat() {
			return dateFormat;
		}

		public void setDateFormat(String dateFormat) {
			this.dateFormat = dateFormat;
		}
	}

	public static class TestBean {
		private Date date;

		private Date[] dates;

		public Date[] getDates() {
			return dates;
		}

		public void setDates(Date[] dates) {
			this.dates = dates;
		}

		public Date getDate() {
			return date;
		}

		public void setDate(Date d) {
			this.date = d;
		}
	}

	public static void main(String[] args) {
		TestBean b = new TestBean();
		b.setDate(DateTimeUtil.date(2007, 11, 11));
		// b.setDates(new Date[] { new Date(), new Date() });
		String ret = JsonUtil.toJsonString(b);
		System.out.println("结果: " + ret);

		TestBean b2 = new TestBean();
		b2 = JsonUtil.getObjectFromJsonString(ret, TestBean.class);
		System.out.println(DateTimeUtil.formatDate(b2.getDate()));
		System.out.println(DateTimeUtil.formatDateTime(b2.getDate()));

	}

}
